using System;
using System.Collections.Generic;
using System.Text;
using Decav.Reality;
using Decav.Data;
using Decav.Geography;
using Decav.Gatsb.Application;

namespace Decav.Gatsb
{
    /// <summary>
    /// Defines a location such as a venue or other place.
    /// </summary>
    [Serializable]
    public class Location
    {


        /// <summary>
        /// Initializes a new <see cref="Location"/>.
        /// </summary>
        /// <param name="name">The name of the location.</param>
        /// <param name="type">The type of the location.</param>
        /// <param name="locale">The locale the location is in, or null if unknown.</param>
        /// <param name="temporary">True when the location needs more information before it can be
        /// determined "complete".</param>
        public Location(string name, LocationType type, Locale locale, bool temporary)
        {
            if (name == null)
                throw new ArgumentNullException("name");


            _tempLocation = temporary;
            _localeId = (locale == null) ? Locale.DefaultLocale.Id : locale.Id;
            _name = name;
            _type = type;
            _id = Guid.NewGuid();
        }

        protected Location(DataRecordAdapter adapt)
        {
            if (adapt == null)
                throw new ArgumentNullException("adapt");

            _searchable = adapt.GetBoolean("Searchable");
            _address = adapt.GetStreetAddress("Address_");
            _description = adapt.GetString("Description");
            _name = adapt.GetString("Name");
            _type = (LocationType)adapt.GetInt32("Type");
            _id = adapt.GetGuid("LocationId");

            _localeId = adapt.GetGuid("LocaleId");
            _coordinates = adapt.GetLatLongPoint("Coordinates");
            _telNumber = adapt.GetPhoneNumber("PhoneNumber");
            _tempLocation = adapt.GetBoolean("TempLocation");
        }

        private bool _tempLocation;
        private LatLongPoint _coordinates;
        private bool _searchable;
        private StreetAddress _address;
        private string _description;
        private string _name;
        private LocationType _type;
        private Guid _id;
        private PhoneNumber _telNumber;
        private Guid _localeId;

        /// <summary>
        /// <para>
        /// Gets or sets if the location is a temporary location that has not yet been verified
        /// </para>
        /// <para>
        /// Locations like this are generally made because the system could not find a location
        /// when a text message was sent to it.
        /// </para>
        /// </summary>
        public bool Temporary
        {
            get
            {
                return _tempLocation;
            }
            set
            {
                _tempLocation = value;
            }
        }

        /// <summary>
        /// Gets the locale that the location is in.
        /// </summary>
        public Locale Locale
        {
            get
            {
                return Locale.GetLocale(_localeId);
            }
            set
            {
                if (value == null)
                    _localeId = Locale.DefaultLocale.Id;

                _localeId = value.Id;
            }
        }

        /// <summary>
        /// Gets or sets the telephone number of the location.
        /// </summary>
        public PhoneNumber TelephoneNumber
        {
            get
            {
                return _telNumber;
            }
            set
            {
                _telNumber = value;
            }
        }

        /// <summary>
        /// Gets the unique identifier of the location.
        /// </summary>
        public Guid Id
        {
            get
            {
                return _id;
            }
        }

        /// <summary>
        /// Gets or sets the coordinates that define where this
        /// location is, in longitude and latitude.
        /// </summary>
        public LatLongPoint GeographicCoordinates
        {
            get
            {
                return _coordinates;
            }
            set
            {
                _coordinates = value;
            }
        }

        /// <summary>
        /// Gets an indication on whether or not this location is searchable by a person other than the creator.
        /// </summary>
        public bool Searchable
        {
            get
            {
                return _searchable;
            }
        }

        /// <summary>
        /// Gets or sets the street address of this location, if available.
        /// </summary>
        public StreetAddress Address
        {
            get
            {
                return _address;
            }
            set
            {
                _address = value;
            }
        }

        /// <summary>
        /// Gets or sets a descriptive name of the location.
        /// </summary>
        public string Description
        {
            get
            {
                return _description;
            }
            set
            {
                _description = value;
            }
        }

        /// <summary>
        /// Gets or sets the location name.
        /// </summary>
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                if (value == null || value.Length == 0)
                    throw new ArgumentNullException("value");

                _name = value;
            }
        }

        /// <summary>
        /// Gets or sets the type of location this location is.
        /// </summary>
        public LocationType Type
        {
            get
            {
                return _type;
            }
            set
            {
                _type = value;
            }
        }

        /// <summary>
        /// Gets the location name as a string, using the default format.
        /// </summary>
        /// <returns>The display name of the location.</returns>
        public override string ToString()
        {
            return GatsbApplication.Current.CurrentLocale.FormatLocationName(this);
        }

        /// <summary>
        /// Gets the location name as a string, using a user-defined format.
        /// </summary>
        /// <param name="format">The location name format to use.</param>
        /// <returns>The display name of the location.</returns>
        public string ToString(LocationNameFormat format)
        {
            return GatsbApplication.Current.CurrentLocale.FormatLocationName(this, format);
        }
    }
}
